#ifndef MODBUS_H
#define MODBUS_H

#include "user_global.h"
#include "device_usart.h"


//==========================================================
// RO_BIT
//==========================================================

typedef enum RO_BIT_INDEX
{
    S1_AT_HOME,                       // 0000    S1电机在原点(关闭). 1: 在原点 0: 不在原点
    S2_AT_HOME,                       // 0001    S2电机在原点(关闭). 1: 在原点 0: 不在原点
    S3_AT_HOME,                       // 0002    S3电机在原点(关闭). 1: 在原点 0: 不在原点
    S4_AT_HOME,                       // 0003    S4电机在原点(关闭). 1: 在原点 0: 不在原点
    S1_AT_LIMIT,                      // 0004    S1电机在限位(打开)位置. 1: 在限位 0: 不在限位
    S2_AT_LIMIT,                      // 0005    S2电机在限位(打开)位置. 1: 在限位 0: 不在限位
    S3_AT_LIMIT,                      // 0006    S3电机在限位(打开)位置. 1: 在限位 0: 不在限位
    S4_AT_LIMIT,                      // 0007    S4电机在限位(打开)位置. 1: 在限位 0: 不在限位
    KEY_S1_PRESSED,                   // 0008    杯盘抽屉启动按钮按下, 1: 按下 0:未按下
    KEY_S2_PRESSED,                   // 0009    左试剂抽屉启动按钮按下, 1: 按下 0:未按下
    KEY_S3_PRESSED,                   // 000A    右试剂抽屉启动按钮按下, 1: 按下 0:未按下
    KEY_S4_PRESSED,                   // 000B    上盖启动按钮按下, 1: 按下 0:未按下
    S1_HOME_SENSOR_ERROR,             // 000C    S1复位传感器故障. 1: 故障 0: 正常
    S2_HOME_SENSOR_ERROR,             // 000D    S2复位传感器故障. 1: 故障 0: 正常
    S3_HOME_SENSOR_ERROR,             // 000E    S3复位传感器故障. 1: 故障 0: 正常
    S4_HOME_SENSOR_ERROR,             // 000F    S4复位传感器故障. 1: 故障 0: 正常
    S1_LIMIT_SENSOR_ERROR,            // 0010    S1限位1传感器故障. 1: 故障 0: 正常
    S2_LIMIT_SENSOR_ERROR,            // 0011    S2限位1传感器故障. 1: 故障 0: 正常
    S3_LIMIT_SENSOR_ERROR,            // 0012    S3限位1传感器故障. 1: 故障 0: 正常
    S4_LIMIT_SENSOR_ERROR,            // 0013    S4限位1传感器故障. 1: 故障 0: 正常
    S1_MOTOR_ERROR,                   // 0014    S1电机故障. 1: 故障 0: 正常
    S2_MOTOR_ERROR,                   // 0015    S2电机故障. 1: 故障 0: 正常
    S3_MOTOR_ERROR,                   // 0016    S3电机故障. 1: 故障 0: 正常
    S4_MOTOR_ERROR,                   // 0017    S4电机故障. 1: 故障 0: 正常
}RO_BIT_INDEX;

__packed typedef struct RO_BIT{
   uchar s1_at_home:1;                       // 0000    S1电机在原点(关闭). 1: 在原点 0: 不在原点
   uchar s2_at_home:1;                       // 0001    S2电机在原点(关闭). 1: 在原点 0: 不在原点
   uchar s3_at_home:1;                       // 0002    S3电机在原点(关闭). 1: 在原点 0: 不在原点
   uchar s4_at_home:1;                       // 0003    S4电机在原点(关闭). 1: 在原点 0: 不在原点
   uchar s1_at_limit:1;                      // 0004    S1电机在限位(打开)位置. 1: 在限位 0: 不在限位
   uchar s2_at_limit:1;                      // 0005    S2电机在限位(打开)位置. 1: 在限位 0: 不在限位
   uchar s3_at_limit:1;                      // 0006    S3电机在限位(打开)位置. 1: 在限位 0: 不在限位
   uchar s4_at_limit:1;                      // 0007    S4电机在限位(打开)位置. 1: 在限位 0: 不在限位
   uchar key_s1_pressed:1;                   // 0008    杯盘抽屉启动按钮按下, 1: 按下 0:未按下
   uchar key_s2_pressed:1;                   // 0009    左试剂抽屉启动按钮按下, 1: 按下 0:未按下
   uchar key_s3_pressed:1;                   // 000A    右试剂抽屉启动按钮按下, 1: 按下 0:未按下
   uchar key_s4_pressed:1;                   // 000B    上盖启动按钮按下, 1: 按下 0:未按下
   uchar s1_home_sensor_error:1;             // 000C    S1复位传感器故障. 1: 故障 0: 正常
   uchar s2_home_sensor_error:1;             // 000D    S2复位传感器故障. 1: 故障 0: 正常
   uchar s3_home_sensor_error:1;             // 000E    S3复位传感器故障. 1: 故障 0: 正常
   uchar s4_home_sensor_error:1;             // 000F    S4复位传感器故障. 1: 故障 0: 正常
   uchar s1_limit_sensor_error:1;            // 0010    S1限位1传感器故障. 1: 故障 0: 正常
   uchar s2_limit_sensor_error:1;            // 0011    S2限位1传感器故障. 1: 故障 0: 正常
   uchar s3_limit_sensor_error:1;            // 0012    S3限位1传感器故障. 1: 故障 0: 正常
   uchar s4_limit_sensor_error:1;            // 0013    S4限位1传感器故障. 1: 故障 0: 正常
   uchar s1_motor_error:1;                   // 0014    S1电机故障. 1: 故障 0: 正常
   uchar s2_motor_error:1;                   // 0015    S2电机故障. 1: 故障 0: 正常
   uchar s3_motor_error:1;                   // 0016    S3电机故障. 1: 故障 0: 正常
   uchar s4_motor_error:1;                   // 0017    S4电机故障. 1: 故障 0: 正常
}RO_BIT;

extern  RO_BIT ro_bit;


#define RO_BIT_FIRST                        ((uchar*)&ro_bit)
#define RO_BIT_COUNT                        0x18

//------------------------------------------
// RW-BIT
//------------------------------------------

typedef struct RW_BIT{
     uchar disable_s1:1;            //  0000   禁止杯盘抽屉动作.   1: 禁止; 0: 允许.
     uchar disable_s2:1;            //  0001   禁止左试剂抽屉动作. 1: 禁止; 0: 允许.
     uchar disable_s3:1;            //  0002   禁止右试剂抽屉动作. 1: 禁止; 0: 允许.
     uchar disable_s4:1;            //  0003   禁止上盖动作.       1: 禁止; 0: 允许.
     uchar unlock_v1:1;             //  0004   杯盘抽屉电磁阀锁定控制. 1: 取消锁定； 0：锁定
     uchar unlock_v2:1;             //  0005   左试剂抽屉电磁阀锁定控制. 1: 取消锁定； 0：锁定
     uchar unlock_v3:1;             //  0006   右试剂电磁阀锁定控制. 1: 取消锁定； 0：锁定
     uchar unlock_v4:1;             //  0007   上盖电磁阀锁定控制. 1: 取消锁定； 0：锁定
     uchar key_long_pressed_s1 : 1; //  0008   检测到按键长按置1，由软件清除
     uchar key_long_pressed_s2 : 1; //  0009   检测到按键长按置1，由软件清除
     uchar key_long_pressed_s3 : 1; //  000A   检测到按键长按置1，由软件清除
}RW_BIT;

extern  RW_BIT rw_bit;

#define RW_BIT_FIRST        ((uchar*)&rw_bit)
#define RW_BIT_COUNT        0x0C


typedef enum RO_LONG_ADD
{
    S1_POS_L = 0x01,
    S1_POS_H,
    S2_POS_L,
    S2_POS_H,
    S3_POS_L,
    S3_POS_H,
    S4_POS_L,
    S4_POS_H,
    S1_DISTANCE_L = 0x0A,
    S1_DISTANCE_H,
    S2_DISTANCE_L = 0x0D,
    S2_DISTANCE_H,
    S3_DISTANCE_L = 0x10,
    S3_DISTANCE_H,
    S4_DISTANCE_L = 0x13,
    S4_DISTANCE_H,
}RO_LONG_ADD;

extern RO_LONG_ADD ro_long_addL[8];
extern RO_LONG_ADD ro_long_addH[8];

#define RO_CHAR_COUNT   0

typedef struct RO_CHAR{
    ushort start;
    ushort end;
}RO_CHAR;

#if RO_CHAR_COUNT
extern RO_CHAR rochar[RO_CHAR_COUNT];
#endif

//==========================================================
// RO-WORD
//==========================================================
__packed typedef struct RO_WORD{
    ushort server_status;               // 服务器状态. 见 `SERVER STATUS`_.
    long pos[MACHINE_COUNT];            // 当前 S1方向电机 坐标,步
    MACHINE_INFO mi[MACHINE_COUNT];     // 运动经过的时间, ms
                                        // 运动经过的距离,步
}RO_WORD;

extern RO_WORD ro_word;

#define RO_WORD_FIRST       ((ushort*)&ro_word.server_status)
#define RO_WORD_END         ((ushort*)&ro_word.z_distance - 1)
#define RO_WORD_COUNT       0x15
#define RO_WORD_SIZE        (RO_WORD_END - RO_WORD_FIRST)

//==========================================================
// RW-WORD
//==========================================================

typedef enum RW_LONG_ADD
{
    S1_MAX_DISTANCE_L = 0x12,
    S1_MAX_DISTANCE_H,
    S2_MAX_DISTANCE_L = 0x15,
    S2_MAX_DISTANCE_H,
    S3_MAX_DISTANCE_L = 0x18,
    S3_MAX_DISTANCE_H,
    S4_MAX_DISTANCE_L = 0x1B,
    S4_MAX_DISTANCE_H,
}RW_LONG_ADD;

extern RW_LONG_ADD rw_long_addL[4];
extern RW_LONG_ADD rw_long_addH[4];

__packed typedef struct RW_WORD{
    ushort action;                      //  0000    当前执行指令
    ushort action_arg[16];              // 0001/16 ACTION参数
    MACHINE_PARAM mp[MACHINE_COUNT];    // 0011   S1 最高速度 0.01 rad/sec^2
                                        // 0012/2 S1 最大行程, 步.
                                        // 0014   S2 最高速度 0.01 rad/sec^2
                                        // 0015/2 S2 最大行程, 步.
                                        // 0017   S3 最高速度 0.01 rad/sec^2
                                        // 0018/2 S3 最大行程, 步.
                                        // 001A   S4 最高速度 0.01 rad/sec^2
                                        // 001B/2 S4 最大行程, 步.
//#ifdef PRODUCT_DEBUG
    ushort second_speed[MACHINE_COUNT];
    ushort second_step[MACHINE_COUNT];
//#endif
    ushort s_home_step_buffer[MACHINE_COUNT - 1];
    ushort s_home_step_flag[MACHINE_COUNT - 1];
}RW_WORD;

extern RW_WORD rw_word;

#define RW_WORD_FIRST       ((ushort*)&rw_word.action)
#define RW_WORD_END         ((ushort*)&rw_word.temp_bias)
#define RW_WORD_COUNT       (0x1D+8+8)
#define RW_WORD_SIZE        (RW_WORD_END - RW_WORD_FIRST)


//------------------------------------------
// 文件
//------------------------------------------
#define FILE_COUNT              0
#define MAX_FILE_REQUEST        2       // 一次请求最大的子记录访问数量

//------------------------------------------
// 诊断
//------------------------------------------
extern ushort  diagnostic;
extern ushort  bus_message_count;
extern ushort  bus_error_count;
extern ushort  bus_exception_count;
extern ushort  server_message_count;
extern ushort  server_no_response_count;
extern ushort  server_exception_count;
extern ushort  server_busy_count;
extern ushort  bus_char_overrun_count;
extern ushort  server_status;
extern uchar   program_status;

extern bit ps_listen_only;                                        // 处于只听模式
extern bit ps_server_busy;                                        // 设备忙

// diagnostic寄存器位定义:


//------------------------------------------
// 事件
//------------------------------------------
#define MAX_EVENT_COUNT                                64                // 2^n
#define MAX_EVENT_MASK                                (MAX_EVENT_COUNT-1)

// 接收事件
#define EVENT_RECEIVED                                0x80        // 接收事件
#define EVENT_BROADCAST                               0x40        // 接收到广播消息
#define EVENT_LISTEN_ONLY                             0x20        // 当前处于只听模式
#define EVENT_CHARRACTER_OVERRUN                      0x10        // 字符过载
#define EVENT_COMMUNICATION_ERROR                     0x02        // 通讯错误

// 发送事件
#define EVENT_SENT                                    0x40        // 发送事件
//#define EVENT_LISTEN_ONLY                           0x20        // 当前处于只听模式
#define EVENT_WRITE_TIMEOUT                           0x10        // 写超时
#define EVENT_EXCEPTION                               0x80        // 异常应答
#define EVENT_BUSY_EXCEPTION                          0x04        // 错误代码 5-6
#define EVENT_ABORT_EXCEPTION                         0x02        // 错误代码 4
#define EVENT_READ_EXCEPTION                          0x01        // 错误代码 1-3

// 进入只听模式事件
#define EVENT_ENTER_LISTEN_ONLY                       0x04        // 进入只听模式事件

// 复位事件
#define EVENT_RESET_PORT                              0x00        // 复位事件

extern uchar event_count;                                        // 事件记数值, event_count索引的event_log为当前事件
extern uchar event_log[MAX_EVENT_COUNT];        // 事件记录

//------------------------------------------
// 异常应答代码
//------------------------------------------
#define ILLEGAL_FUNCTION                        0x01
#define ILLEGAL_DATA_ADDRESS                    0x02
#define ILLEGAL_DATA_VALUE                      0x03
#define SERVER_DEVICE_FAILURE                   0x04
#define ACKNOWLEDGE                             0x05
#define SERVER_DEVICE_BUSY                      0x06
#define MEMORY_PARITY_ERROR                     0x08
#define GATEWAY_PATH_UNAVAILABLE                0x0A
#define GATEWAY_TARGET_NO_RESPONSE              0x0B
#define ILLEGAL_DATA_COUNT                      0x0C
//----------------------------------------------------------------------------------
/*The bytes are coded in memory in Little Endian format.
    The lowest numbered byte in a word is considered the word’s
    least significant byte and the highest numbered byte the most significant.*/
//----------------------------------------------------------------------------------

ushort from_little_endian_16(ushort n);
ulong  from_little_endian_32(ulong n);



bit Uart0_FrameEnded(void);
void No_Response(void);
void Response(void);
void Exception_Response(uchar err);
void Process_Request(void);

uchar Read_RO_bit(ushort addr, uchar n);
uchar Read_RW_bit(ushort addr, uchar n);
//void Write_bit(ushort addr, uchar val);
void Write_RO_bit(ushort addr, uchar val, uchar n);
void Write_bit(ushort addr, uchar val, uchar n);
uchar Test_Bit(uchar *bits, ushort addr);
void Set_Bit(uchar *bits, ushort addr, bit val);
void Set_RO_Bit(ushort addr);
void Reset_RO_Bit(ushort addr);
ushort Read_RO_word(ushort addr);
ushort Read_RW_word(ushort addr);
void Write_word(ushort addr, ushort val);

uchar Read_Exception(void);
void Diagnose(void);
void Log_Event(uchar event);

void Read_Identification(void);

#if FILE_COUNT
// 文件操作
void Reset_File(uchar fid);
void Append_File(uchar fid, ushort *rec,ushort n);
//void Append_File(uchar fid, ushort rec);
void Append_File_Word(uchar fid, ushort rec);
ushort Read_File(uchar fid, ushort addr);
void Write_File(uchar fid, ushort addr, ushort val);
ushort File_Size(uchar fid);
void Set_File_Size(uchar fid, ushort size);
#endif//FILE_COUNT








#endif // MODBUS_H
